#pragma once

#include <linux/list.h>
#include <linux/spinlock.h>

struct swait_queue_head
{
	raw_spinlock_t lock;
	struct list_head task_list;
};

#define __SWAIT_QUEUE_HEAD_INITIALIZER(name) {     \
	.lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock),   \
	.task_list = LIST_HEAD_INIT((name).task_list), \
}

struct swait_queue
{
	struct task_struct *task;
	struct list_head task_list;
};

#define __SWAITQUEUE_INITIALIZER(name) {           \
	.task = current,                               \
	.task_list = LIST_HEAD_INIT((name).task_list), \
}

#define DECLARE_SWAITQUEUE(name) \
	struct swait_queue name = __SWAITQUEUE_INITIALIZER(name)

extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
									struct lock_class_key *key);

#define init_swait_queue_head(q)                  \
	do                                            \
	{                                             \
		static struct lock_class_key __key;       \
		__init_swait_queue_head((q), #q, &__key); \
	} while (0)

extern void swake_up_one(struct swait_queue_head *q);
extern void swake_up_all(struct swait_queue_head *q);
extern void swake_up_locked(struct swait_queue_head *q, int wake_flags);

void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
